package flex.cc.store.util;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * @Description: AES加密
 * @Author: panxicheng-ghq
 * @CreateDate: 2018/09/12
 * @CreateBy IntelliJ IDEA
 */
public class AESSingleUtil {

  private static Log logger = LogFactory.getLog(AESSingleUtil.class);

  private static SecretKeySpec sks;
  private static String insType;
  public static final String DEFAULT_INS_TYPE = "AES/ECB/PKCS5Padding";

  public static void initMethod(byte[] key, String insType) throws Exception {
    sks = null;
//  insType = null;
    if (key == null) {
      throw new NullPointerException("Please input key with valid value");
    } else {
      byte[] newKey = new byte[16];

      for (int i = 0; i < key.length; ++i) {
        newKey[i % 16] ^= key[i];
      }

      sks = new SecretKeySpec(newKey, "AES");
      AESSingleUtil.insType = insType;
    }
  }

  /**
   * 加密数据
   *
   * @param value
   * @return
   */
  public static String encrypt(String value, String secret_key) {
    if (StringUtils.isBlank(value)) {
      return value;
    }
    value = value.trim();
    if (value.length() % 16 == 0) {
      try {
        String decValue = new String(decrypt(hexString2Bytes(value), secret_key), "utf-8");
        if (StringUtils.isNotBlank(decValue)) {
          logger.info("EncAndDecUtil#setDataEnc 原数据可以被解密，返回原值，原值：" + value + "，解密后：" + decValue);
          return value;
        }
      } catch (Exception e2) {
      }
    }
    try {
      return bytes2HexString(encrypt(value.getBytes("utf-8"), secret_key));
    } catch (Exception e) {
      logger.info("EncAndDecUtil#setDataEnc 加密发生异常：" + e + "，输入值为：" + value);
      return value;
    }
  }

  /**
   * 解密数据
   *
   * @param encValue
   * @return
   */
  public static String decrypt(String encValue, String secret_key) {
    try {
      if (StringUtils.isBlank(encValue)) {
        return encValue;
      }
      encValue = encValue.trim();
      String decValue = new String(decrypt(hexString2Bytes(encValue), secret_key), "utf-8");
      return StringUtils.isBlank(decValue) ? encValue : decValue;
    } catch (Exception e) {
      logger.error("EncAndDecUtil#setDataDec 解密发生异常 输入值为：" + encValue, e);
      return encValue;
    }
  }

  private static byte[] encrypt(byte[] data, String secret_key) throws Exception {

    if (StringUtils.isBlank(secret_key)) {
      throw new Exception("Please configure the ec.project.db.eccreat.aeskey env param.");
    }
    initMethod(secret_key.getBytes("utf-8"), "AES/ECB/PKCS5Padding");
    return encryptY(data);
  }

  private static byte[] decrypt(byte[] content, String secret_key) throws Exception {

    if (StringUtils.isBlank(secret_key)) {
      throw new Exception("Please configure the ec.project.db.eccreat.aeskey env param.");
    }
    initMethod(secret_key.getBytes("utf-8"), "AES/ECB/PKCS5Padding");
    return decryptY(content);
  }

  /**
   * @Description: 方法作用
   * @Param: 入参
   * @Author: yxn
   * @CreateDate: 2018/10/18 11:10 AM
   */
  public static byte[] encryptY(String content) throws Exception {
    return encryptY(content.getBytes("utf-8"));
  }

  public static byte[] encryptY(byte[] byteContent) throws Exception {
    Cipher encrypter = Cipher.getInstance(insType);
    encrypter.init(1, sks);
    return encrypter.doFinal(byteContent);
  }

  public static byte[] decryptY(byte[] content) throws Exception {
    Cipher decrypter = Cipher.getInstance(insType);
    decrypter.init(2, sks);
    return decrypter.doFinal(content);
  }

  public static byte[] hexString2Bytes(String src) {
    int l = src.length() / 2;
    byte[] ret = new byte[l];

    for (int i = 0; i < l; ++i) {
      ret[i] = Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
    }

    return ret;
  }

  public static String bytes2HexString(byte[] b) {
    StringBuffer result = new StringBuffer();

    for (int i = 0; i < b.length; ++i) {
      String hex = Integer.toHexString(b[i] & 255);
      if (hex.length() == 1) {
        hex = '0' + hex;
      }

      result.append(hex.toUpperCase());
    }

    return result.toString();
  }
}
